/*
 * Created on 2007-11-15
 *
 * TODO
 */
package jacky.lanlan.song.closure;

import java.util.*;
import java.util.concurrent.*;

/**
 * “闭包”实用工具类。
 * @author Jacky.Song
 */
public abstract class ClosureUtils {

	/**
	 * 反转给定判断的语意。该方法将返回一个相反语意的Judgement。
	 * <p>
	 * 比如：<code>Judgement.EMPTY_STRING</code>
	 * 取反后的语意就是“非空字符串判断”。
	 * @param <T> Judgement的类型参数
	 * @param judge 想要取反的判断
	 * @return 反转judge语意的判断
	 */
	public static <T> Judgment<T> reverse(final Judgment<T> judge) {
		return new Judgment<T>() {
			public boolean canPass(T arg) {
				return !judge.canPass(arg);
			}
		};
	}

	/**
	 * <b style="color:red">阻塞方法。</b>
	 * <p>
	 * 检测items的每个元素，看是否都可以通过给定的判断condition，如果不符合就阻塞线程，
	 * 一直检测，直到所有元素都通过判断为止。
	 * <p>
	 * <i>注意，根据语意，这个方法有可能永远阻塞(例如任务本身有问题导致永远不能通过判断)。</i>
	 * @param <T> 集合元素类型
	 * @param items 集合
	 * @param condition 对集合中每个元素的判断
	 * @param executor 用来执行判断任务的Executor
	 */
	public static <T> void waitUntilAllPass(Collection<T> items,final Judgment<T> condition,
			final Executor executor){
    final CountDownLatch doneSignal = new CountDownLatch(items.size());
    for (final T item:items) {
    	//提交给线程池来执行判断
    	executor.execute(new Runnable() {
				public void run() {
					boolean pass= condition.canPass(item);//执行任务
					if(!pass) {
						executor.execute(this);//如果没有通过，重新把自己放回池中
					}
					else {
						doneSignal.countDown();//如果通过，发出完成信号
					}
				}
			});
    }
    try {
			doneSignal.await();//阻塞，直到所有任务完成
		}
		catch (InterruptedException e) {
			throw new RuntimeException(e);
		}
	}
	
}
